/**
 * @file Stimer.c
 * @author 七味 (heqiweii@163.com)
 * @brief 裸机软件定时器,需要硬件中断做时基
 * @version 0.2
 * @date 2021-12-07
 * @copyright Copyright (c) 2021
 */
#include "stimer.h"
/**
 * @brief 定时器tick寄存器
 * 
 */
uint32_t stimer_tick = 0;
/**
 * @brief 保存了上一次的tick值
 *
 */
uint32_t stimer_tick_last = 0;
/**
 * @brief 定时器句柄
 * 
 */
static stimer_t* timer_handle = NULL;

#if defined(STIMER_CUSTOM_MEM)

#else
/**
 * @brief 内存标记
 */
struct stimer_mem
{
	stimer_t timer;
	uint8_t used;
};
/**
 * @brief 定时器内存池
 */
static struct stimer_mem stimer_mem_pool[STIMER_MAX_NUMBER] = {0};
/**
 * @brief 申请动态内存
 * 
 * @param size 申请大小
 * @return void* 内存首地址
 */
void* malloc(uint32_t size)
{
	stimer_t* ret = NULL;
	for(uint32_t i = 0; i < STIMER_MAX_NUMBER; i ++)
	{
		if(stimer_mem_pool[i].used == 0)
		{
			stimer_mem_pool[i].used = 1;
			ret = &stimer_mem_pool[i].timer;
			break;
		}
	}
	return ret;
}
/**
 * @brief 释放动态内存
 * 
 * @param ptr 内存首地址
 */
void free(void* ptr)
{
	if(ptr == NULL)
		return;
	for(uint32_t i = 0; i < STIMER_MAX_NUMBER; i ++)
	{
		if(&stimer_mem_pool[i].timer == ptr)
		{
			stimer_mem_pool[i].used = 0;
			return;
		}
	}
}
#endif
/**
 * @brief 产生一个定时器
 * 
 * @param timeout 超时回调
 * @param time 定时时间
 * @param user_data 回调参数
 * @return stimer_t* 定时器句柄
 */
stimer_t* stimer_create(void(*timeout)(struct stimer*), uint32_t tick, void* user_data)
{
	stimer_t* timer = (stimer_t*)malloc(sizeof(stimer_t));
	if(!timer)return NULL;
	/**/
	timer->count = 0;
	timer->init_count = tick;
	timer->init_count_copy = timer->init_count;
	timer->running = 0;
	timer->started = 0;
	timer->timeout_cb = timeout;
	timer->next = NULL;
	timer->prev = NULL;
	timer->user_data = user_data;
	/**/
	if (timer_handle == NULL)
	{
		timer_handle = timer;
		return timer;
	}
	/**/
	stimer_t* timer_itor = NULL;
	for(timer_itor = timer_handle; timer_itor->next != NULL; timer_itor = timer_itor->next);
	timer_itor->next = timer;
	timer->prev = timer_itor;
	return timer;
}
/**
 * @brief 删除一个定时器
 * 
 * @param timer 定时器句柄
 */
void stimer_delete(stimer_t* timer)
{
	if(timer == NULL)
		return;
	if (!timer->prev)
	{
		timer->next->prev = NULL;
		timer_handle = timer->next;
	}
	else if (!timer->next)
	{
		timer->prev->next = NULL;
	}
	else
	{
		timer->next->prev = timer->prev;
		timer->prev->next = timer->next;
	}
	free(timer);
}

/**
 * @brief 定时器轮询
 * 
*/
void stimer_handler(void)
{
	uint32_t tmp_tick = stimer_tick;
	for(stimer_t* timer_itor = timer_handle; timer_itor != NULL; timer_itor = timer_itor->next)
	{
		if(!timer_itor->running)continue;
		/*溢出处理*/
		if(tmp_tick < stimer_tick_last)
		{
			uint32_t poll_interval = 0, remainder = 0;
			/*计算了轮询间隔*/
			poll_interval = (0xFFFFFFFF - stimer_tick_last) + tmp_tick;
			/*计算了剩余时间*/
			remainder = (stimer_tick_last - timer_itor->count) + poll_interval;
			/*计算新的超时时间*/
			timer_itor->init_count = timer_itor->init_count - remainder;
			/*重置count*/
			timer_itor->count = tmp_tick;
		}
		/*超时处理*/
		if((tmp_tick - timer_itor->count) >= timer_itor->init_count)
		{
			timer_itor->count = tmp_tick;
			if(timer_itor->init_count != timer_itor->init_count_copy)
			{
				timer_itor->init_count = timer_itor->init_count_copy;
			}
			timer_itor->timeout_cb(timer_itor);
		}
	}
	stimer_tick_last = tmp_tick;
}
/**
 * @brief 启动定时器
 * 
 * @param timer 定时器句柄
 */
void stimer_start(stimer_t* timer)
{
	if (!timer->started)
	{
		timer->count = stimer_tick;
		timer->started = 1;
	}
	timer->running = 1;
}
/**
 * @brief 复位定时器
 * 
 * @param timer 定时器句柄
 */
void stimer_reset(stimer_t* timer)
{
	timer->count = stimer_tick;
}
/**
 * @brief 停止定时器
 * 
 * @param timer 定时器句柄
 */
void stimer_stop(stimer_t* timer)
{
	timer->running = 0;
}